package cn.le.netty.cient;

import cn.le.netty.handler.HeartBeatReqHandler;
import cn.le.netty.handler.ActiveHandler;
import cn.le.netty.inf.NettyHandler;
import cn.le.netty.messagePack.MessagePackDecoder;
import cn.le.netty.messagePack.MessagePackEncoder;
import cn.le.netty.util.NettyFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.util.CollectionUtils;

import java.util.List;

final class Client {

    public static void connection(String ip,int port){
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap client = new Bootstrap();//创建客户端
            client.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)//允许接受大块的数据返回
                    .handler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //拆包解码器
                            socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535,0,
                                    4,0,4));
                            //把拆包后的byte数据转成对象
                            socketChannel.pipeline().addLast(new MessagePackDecoder());
                            //定长编码器,按照第一个位置保持数据长度
                            socketChannel.pipeline().addLast(new LengthFieldPrepender(4));
                            //对象序列化
                            socketChannel.pipeline().addLast(new MessagePackEncoder());
                            //心跳检测
                            socketChannel.pipeline().addLast(new IdleStateHandler(60,90,150));
                            socketChannel.pipeline().addLast(new ActiveHandler(ip,port));
                            //心跳,重连操作
                            socketChannel.pipeline().addLast(new HeartBeatReqHandler());
                            List<NettyHandler> nettyHandlers = NettyFactory.getNettyHandlers();
                            if (!CollectionUtils.isEmpty(nettyHandlers)){
                                nettyHandlers.forEach(handler->{
                                    socketChannel.pipeline().addLast(handler);
                                });
                            }
                        }
                    });
            ChannelFuture channelFuture = client.connect(ip,port).sync();//等待链接处理
            channelFuture.channel().closeFuture().sync();//等待关闭链接
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
            System.out.println("group loop 释放");
        }
    }
}
